package org.jflame.commons.util;

import java.lang.Thread.UncaughtExceptionHandler;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.apache.commons.lang3.concurrent.BasicThreadFactory.Builder;
import org.apache.commons.lang3.concurrent.ConcurrentException;
import org.apache.commons.lang3.concurrent.ConcurrentUtils;
import org.apache.commons.lang3.concurrent.LazyInitializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public final class Threads {

    // 定义一个延迟初始的定时任务执行线程池,用于执行一些简单的定时任务
    private ScheduledExecutorInitializer scheduledExecutorInitializer = new ScheduledExecutorInitializer(3);
    private static Threads instance = new Threads();

    /**
     * 线程未捕获异常处理类
     * 
     * @author charles.zhang
     */
    public static class LogUncaughtExceptionHandler implements UncaughtExceptionHandler {

        Logger log = LoggerFactory.getLogger("LogUncaughtExceptionHandler");

        @Override
        public void uncaughtException(Thread t, Throwable e) {
            log.error("线程异常", e);
        }
    }

    private Threads() {
    }

    /**
     * 设置一个全局线程未捕获异常处理类,日志记录异常
     * 
     * @see LogUncaughtExceptionHandler
     */
    public static void logUncaughtException() {
        Thread.setDefaultUncaughtExceptionHandler(new LogUncaughtExceptionHandler());
    }

    /**
     * 线程休眠，忽略InterruptedException异常
     * 
     * @param timeout 休眠时间,单位毫秒
     */
    public static void sleep(int timeout) {
        try {
            TimeUnit.MILLISECONDS.sleep(timeout);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 构造一个可重用的线程池,线程池最大线程数设定为200,闲置时间120秒
     * 
     * @return
     */
    public static ExecutorService newCachedThreadPool() {
        Builder builder = new BasicThreadFactory.Builder().daemon(true);
        if (Thread.getDefaultUncaughtExceptionHandler() == null) {
            builder.uncaughtExceptionHandler(new LogUncaughtExceptionHandler());
        }
        return new ThreadPoolExecutor(0, 200, 120L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(),
                builder.build());
    }

    public static ScheduledExecutorService getScheduledExecutor() {
        return ConcurrentUtils.initializeUnchecked(Threads.instance.scheduledExecutorInitializer);
    }

    static class ScheduledExecutorInitializer extends LazyInitializer<ScheduledExecutorService> {

        private final int corePoolSize;

        public ScheduledExecutorInitializer(int corePoolSize) {
            this.corePoolSize = corePoolSize;
        }

        protected ScheduledExecutorService initialize() throws ConcurrentException {
            return new ScheduledThreadPoolExecutor(corePoolSize, new BasicThreadFactory.Builder().daemon(true)
                    .build());
        }
    }
}
